package com.hb.aspect;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

// 面向注解的切面声明有一个明显的劣势：必须能够为通知类添加注解。为了做到这一点，必须要有源码。如果没有源码的话，或者不想将 AspectJ 注解放到你的代码之中，可以在 XML 配置文件中声明切面。
@Aspect
public class TrackCounter {
    private Map<Integer, Integer> trackCounts = new HashMap<Integer, Integer>();

    // 这里切点还声明了要提供给通知方法的参数，其中 args(trackNumber) 限定符表明传递给 trackPlayed() 方法的 int 类型参数也会传递到通知中去。
    // 切点定义指定的 playTrack 方法参数的形参是一个 int 类型参数，那么如果 com.hb.interfaces.CompactDisc 下面还有一个没有参数的 playTrack 方法就不会被匹配为切点。
    // 参数的名称 trackNumber 也与切点方法签名中的参数相匹配。args() 是声明通知的参数。
    @Pointcut("execution(* com.hb.interfaces.CompactDisc.playTrack(int)) && args(trackNumber)")
    public void trackPlayed(int trackNumber) {
    }

    @Before("trackPlayed(trackNumber)")
    public void countTrack(int trackNumber) {
        int currentCount = getPlayCount(trackNumber);
        trackCounts.put(trackNumber, currentCount + 1);
        System.out.println("磁道" + trackNumber + "播放+1");
    }

    public int getPlayCount(int trackNumber) {
        return trackCounts.containsKey(trackNumber) ? trackCounts.get(trackNumber) : 0;
    }
}
